home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / nfs / nfswatch4.0 / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-01  |  24.3 KB  |  1,159 lines

  1. #ifndef lint
  2. static char *RCSid = "$Header: /home/harbor/davy/system/nfswatch/RCS/util.c,v 4.0 1993/03/01 19:59:00 davy Exp $";
  3. #endif
  4.  
  5. #include "os.h"
  6.  
  7. /*
  8.  * util.c - miscellaneous utility routines.
  9.  *
  10.  * David A. Curry                Jeffrey C. Mogul
  11.  * Purdue University                Digital Equipment Corporation
  12.  * Engineering Computer Network            Western Research Laboratory
  13.  * 1285 Electrical Engineering Building        250 University Avenue
  14.  * West Lafayette, IN 47907-1285        Palo Alto, CA 94301
  15.  * davy@ecn.purdue.edu                mogul@decwrl.dec.com
  16.  *
  17.  * $Log: util.c,v $
  18.  * Revision 4.0  1993/03/01  19:59:00  davy
  19.  * NFSWATCH Version 4.0.
  20.  *
  21.  * Revision 3.12  1993/02/24  17:44:45  davy
  22.  * Added -auth mode, changes to -proc mode, -map option, -server option.
  23.  *
  24.  * Revision 3.11  1993/01/20  14:52:30  davy
  25.  * Added -T maxtime option.
  26.  *
  27.  * Revision 3.10  1993/01/16  19:08:59  davy
  28.  * Corrected Jeff's address.
  29.  *
  30.  * Revision 3.9  1993/01/15  19:33:39  davy
  31.  * Miscellaneous cleanups.
  32.  *
  33.  * Revision 3.8  1993/01/15  16:32:41  davy
  34.  * Fixed up getmntent code for SVR4/SUNOS5 and IRIX40.
  35.  *
  36.  * Revision 3.7  1993/01/15  15:43:36  davy
  37.  * Assorted changes for porting to Solaris 2.x/SVR4.
  38.  *
  39.  * Revision 3.6  1993/01/14  03:41:21  davy
  40.  * Changed "Yellow Pages/NIS" to "YP/NIS/NIS+".
  41.  *
  42.  * Revision 3.5  1993/01/13  20:18:17  davy
  43.  * Put in OS-specific define scheme, and merged in Tim Hudson's code for
  44.  * SGI systems (as yet untested).
  45.  *
  46.  * Revision 3.4  1993/01/13  15:12:05  davy
  47.  * Added background mode.
  48.  *
  49.  * Revision 3.3  1993/01/13  13:00:04  davy
  50.  * Fixed a bug in finish() routine, closing too many file descriptors.
  51.  *
  52.  * Revision 3.2  1992/07/24  18:47:57  mogul
  53.  * Added FDDI support
  54.  *
  55.  * Revision 3.1  1992/07/23  00:01:17  mogul
  56.  * Proper use of if_fd[] variable.
  57.  *
  58.  * Revision 3.0  1991/01/23  08:23:29  davy
  59.  * NFSWATCH Version 3.0.
  60.  *
  61.  * Revision 1.4  91/01/17  10:18:08  davy
  62.  * New features from Jeff Mogul.
  63.  * 
  64.  * Revision 1.6  91/01/07  15:35:20  mogul
  65.  * Must rebuild client hash table after sorting
  66.  * 
  67.  * Revision 1.5  91/01/07  14:09:10  mogul
  68.  * Improved sortbyusage stuff
  69.  * 
  70.  * Revision 1.4  91/01/04  14:14:27  mogul
  71.  * Support for client counters
  72.  * 
  73.  * Revision 1.3  91/01/03  17:42:20  mogul
  74.  * Support for per-procedure counters
  75.  * 
  76.  * Revision 1.2  90/08/17  15:47:50  davy
  77.  * NFSWATCH Version 2.0.
  78.  * 
  79.  * Revision 1.1  88/11/29  11:21:05  davy
  80.  * NFSWATCH Release 1.0
  81.  * 
  82.  */
  83. #include <sys/param.h>
  84. #include <sys/stat.h>
  85. #include <sys/time.h>
  86. #include <curses.h>
  87. #include <stdio.h>
  88. #ifdef IRIX40
  89. #include <mntent.h>
  90. #endif
  91. #ifdef SUNOS4
  92. #include <mntent.h>
  93. #include <exportent.h>
  94. #endif
  95. #ifdef ultrix
  96. #include <sys/mount.h>
  97. #endif
  98. #ifdef SVR4
  99. #include <sys/mnttab.h>
  100. #endif
  101.  
  102. #include "nfswatch.h"
  103. #include "externs.h"
  104. #include "screen.h"
  105.  
  106. /*
  107.  * clear_vars - set interval counters to zero.
  108.  */
  109. void
  110. clear_vars()
  111. {
  112.     register int i;
  113.  
  114.     int_pkt_total = 0;
  115.     int_pkt_drops = 0;
  116.     int_dst_pkt_total = 0;
  117.  
  118.     for (i = 0; i < PKT_NCOUNTERS; i++)
  119.         pkt_counters[i].pc_interval = 0;
  120.  
  121.     for (i = 0; i < nnfscounters; i++) {
  122.         (void) bzero((char *) nfs_counters[i].nc_proc,
  123.             MAXNFSPROC * sizeof(Counter));
  124.  
  125.         nfs_counters[i].nc_interval = 0;
  126.     }
  127.  
  128.     for (i = 0; i < nfilecounters; i++) {
  129.         (void) bzero((char *) fil_counters[i].fc_proc,
  130.             MAXNFSPROC * sizeof(Counter));
  131.  
  132.         fil_counters[i].fc_interval = 0;
  133.     }
  134.  
  135.     for (i = 0; i < MAXNFSPROC; i++) {
  136.         prc_counters[i].pr_interval = 0;
  137.         prc_counters[i].pr_complete = 0;
  138.         prc_counters[i].pr_response = 0;
  139.         prc_counters[i].pr_respsqr = 0;
  140.         prc_counters[i].pr_maxresp = 0;
  141.     }
  142.  
  143.     for (i = 0; i < nclientcounters; i++)
  144.         clnt_counters[i].cl_interval = 0;
  145.  
  146.     for (i = 0; i < nauthcounters; i++)
  147.         auth_counters[i].ac_interval = 0;
  148.  
  149.     for (i = 0; i < NFSCALLHASHSIZE; i++)
  150.         nfs_calls[i].used = 0;
  151. }
  152.  
  153. /*
  154.  * savestr - save a string in dynamically allocated memory.
  155.  */
  156. char *
  157. savestr(s)
  158. register char *s;
  159. {
  160.     char *malloc();
  161.     register char *str;
  162.  
  163.     str = malloc(strlen(s) + 1);
  164.  
  165.     if (str == NULL) {
  166.         (void) fprintf(stderr, "%s: out of memory.\n", pname);
  167.         finish(-1);
  168.     }
  169.  
  170.     (void) strcpy(str, s);
  171.     return(str);
  172. }
  173.  
  174. /*
  175.  * prtime - convert a time to hh:mm:ss.
  176.  */
  177. char *
  178. prtime(sec)
  179. time_t sec;
  180. {
  181.     int hh, mm, ss;
  182.     static char tbuf[16];
  183.  
  184.     hh = sec / 3600;
  185.     sec %= 3600;
  186.  
  187.     mm = sec / 60;
  188.     sec %= 60;
  189.  
  190.     ss = sec;
  191.  
  192.     (void) sprintf(tbuf, "%02d:%02d:%02d", hh, mm, ss);
  193.     return(tbuf);
  194. }
  195.  
  196. /*
  197.  * error - print an error message preceded by the program name.
  198.  */
  199. void
  200. error(str)
  201. register char *str;
  202. {
  203.     char buf[BUFSIZ];
  204.  
  205.     (void) sprintf(buf, "%s: %s", pname, str);
  206.     (void) perror(buf);
  207. }
  208.  
  209. /*
  210.  * finish - clean up and exit.
  211.  */
  212. void
  213. finish(code)
  214. int code;
  215. {
  216.     int i;
  217.  
  218.     /*
  219.      * Close the nit device.
  220.      */
  221.     for (i = 0; i < ninterfaces; i++) {
  222.         if (if_fd[i] >= 0)
  223.         (void) close(if_fd[i]);
  224.     }
  225.  
  226.     /*
  227.      * End curses.
  228.      */
  229.     if (screen_inited) {
  230. #ifdef nocrmode
  231.         (void) nocrmode();
  232. #else
  233.         (void) nocbreak();
  234. #endif
  235.         (void) echo();
  236.  
  237.         (void) move(SCR_PROMPT_Y, SCR_PROMPT_X0);
  238.         (void) clrtoeol();
  239.         (void) refresh();
  240.         (void) endwin();
  241.     }
  242.  
  243.     if (logging) {
  244.         (void) fprintf(logfp, "#\n# endlog\n#\n");
  245.         (void) fclose(logfp);
  246.     }
  247.  
  248.     (void) putchar('\n');
  249.  
  250.     if (code < 0)
  251.         (void) exit(-code);
  252.  
  253.     (void) exit(0);
  254. }
  255.  
  256. /*
  257.  * setup_pkt_counters - set up packet counter screen coordinates.
  258.  */
  259. void
  260. setup_pkt_counters()
  261. {
  262.     register int i, j;
  263.  
  264.     (void) bzero((char *) pkt_counters,
  265.         PKT_NCOUNTERS * sizeof(PacketCounter));
  266.  
  267.     /*
  268.      * Set up the strings.
  269.      */
  270.     pkt_counters[PKT_NDREAD].pc_name = "ND Read";
  271.     pkt_counters[PKT_NDWRITE].pc_name = "ND Write";
  272.     pkt_counters[PKT_NFSREAD].pc_name = "NFS Read";
  273.     pkt_counters[PKT_NFSWRITE].pc_name = "NFS Write";
  274.     pkt_counters[PKT_NFSMOUNT].pc_name = "NFS Mount";
  275.     pkt_counters[PKT_YELLOWPAGES].pc_name = "YP/NIS/NIS+";
  276.     pkt_counters[PKT_RPCAUTH].pc_name = "RPC Authorization";
  277.     pkt_counters[PKT_OTHERRPC].pc_name = "Other RPC Packets";
  278.     pkt_counters[PKT_TCP].pc_name = "TCP Packets";
  279.     pkt_counters[PKT_UDP].pc_name = "UDP Packets";
  280.     pkt_counters[PKT_ICMP].pc_name = "ICMP Packets";
  281.     pkt_counters[PKT_ROUTING].pc_name = "Routing Control";
  282.     pkt_counters[PKT_ARP].pc_name = "Address Resolution";
  283.     pkt_counters[PKT_RARP].pc_name = "Reverse Addr Resol";
  284.     pkt_counters[PKT_BROADCAST].pc_name = "Ethernet/FDDI Bdcst";
  285.     pkt_counters[PKT_OTHER].pc_name = "Other Packets";
  286.  
  287.     /*
  288.      * Set screen coordinates for everything.
  289.      */
  290.     for (i = 0, j = PKT_NCOUNTERS/2; i < PKT_NCOUNTERS/2; i++, j++) {
  291.         pkt_counters[i].pc_namex = SCR_PKT_NAME_X;
  292.         pkt_counters[j].pc_namex = SCR_PKT_NAME_X + SCR_MIDDLE;
  293.         pkt_counters[i].pc_namey = SCR_PKT_Y + i;
  294.         pkt_counters[j].pc_namey = SCR_PKT_Y + i;
  295.  
  296.         pkt_counters[i].pc_intx = SCR_PKT_INT_X;
  297.         pkt_counters[j].pc_intx = SCR_PKT_INT_X + SCR_MIDDLE;
  298.         pkt_counters[i].pc_inty = SCR_PKT_Y + i;
  299.         pkt_counters[j].pc_inty = SCR_PKT_Y + i;
  300.  
  301.         pkt_counters[i].pc_totx = SCR_PKT_TOT_X;
  302.         pkt_counters[j].pc_totx = SCR_PKT_TOT_X + SCR_MIDDLE;
  303.         pkt_counters[i].pc_toty = SCR_PKT_Y + i;
  304.         pkt_counters[j].pc_toty = SCR_PKT_Y + i;
  305.  
  306.         pkt_counters[i].pc_pctx = SCR_PKT_PCT_X;
  307.         pkt_counters[j].pc_pctx = SCR_PKT_PCT_X + SCR_MIDDLE;
  308.         pkt_counters[i].pc_pcty = SCR_PKT_Y + i;
  309.         pkt_counters[j].pc_pcty = SCR_PKT_Y + i;
  310.     }
  311. }
  312.  
  313. /*
  314.  * setup_nfs_counters- setup NFS counter screen coordinates, file system
  315.  *               names.
  316.  */
  317. void
  318. setup_nfs_counters()
  319. {
  320.     FILE *fp;
  321.     struct stat st;
  322.     register int i, j;
  323.     register NFSCounter *nc;
  324. #ifdef IRIX40
  325.     register struct mntent *mnt;
  326. #endif
  327. #ifdef SUNOS4
  328.     register struct mntent *mnt;
  329. #endif
  330. #ifdef SVR4
  331.     struct mnttab mnttab;
  332.     register struct mnttab *mnt = &mnttab;
  333. #endif
  334. #ifdef ultrix
  335.     int dummy, nmnts;
  336.     static struct fs_data fsData[MAXEXPORT];
  337. #endif
  338.  
  339.     (void) bzero((char *) nfs_counters,
  340.         MAXEXPORT * sizeof(NFSCounter));
  341.  
  342.     /*
  343.      * If we're not watching our own host, we can't look
  344.      * for mounted file systems.
  345.      */
  346.     if (strcmp(myhost, dsthost) != 0) {
  347.         sort_nfs_counters();
  348.         learnfs = 1;
  349.         return;
  350.     }
  351.  
  352. #ifdef IRIX40
  353.     /*
  354.      * Open the list of mounted file systems.
  355.      */
  356.     if ((fp = setmntent(MOUNTED, "r")) == NULL) {
  357.         error(MOUNTED);
  358.         finish(-1);
  359.     }
  360.  
  361.     nc = nfs_counters;
  362.  
  363.     /*
  364.      * Save the first MAXEXPORT file systems of type "4.2"
  365.      * which have been exported.  These are the ones which can
  366.      * be mounted through NFS.
  367.      */
  368.     while ((mnt = getmntent(fp)) != NULL) {
  369.         if (strcmp(mnt->mnt_type, MNTTYPE_EFS) != 0 &&
  370.             strcmp(mnt->mnt_type, MNTTYPE_BELL) != 0)
  371.             continue;
  372.  
  373.         if (nnfscounters < MAXEXPORT) {
  374.             if (stat(mnt->mnt_dir, &st) < 0)
  375.                 continue;
  376.  
  377.             /*
  378.              * Not exported; skip it.
  379.              */
  380.             if (!is_exported(st.st_dev))
  381.                 continue;
  382.  
  383.             nc->nc_dev = st.st_dev;
  384.             nc->nc_name = savestr(mnt->mnt_dir);
  385.  
  386.             nnfscounters++;
  387.             nc++;
  388.         }
  389.     }
  390.  
  391.     (void) endmntent(fp);
  392. #endif /* IRIX40 */
  393.  
  394. #ifdef SUNOS4
  395.     /*
  396.      * Open the list of mounted file systems.
  397.      */
  398.     if ((fp = setmntent(MOUNTED, "r")) == NULL) {
  399.         error(MOUNTED);
  400.         finish(-1);
  401.     }
  402.  
  403.     nc = nfs_counters;
  404.  
  405.     /*
  406.      * Save the first MAXEXPORT file systems of type "4.2"
  407.      * which have been exported.  These are the ones which can
  408.      * be mounted through NFS.
  409.      */
  410.     while ((mnt = getmntent(fp)) != NULL) {
  411.         if (strcmp(mnt->mnt_type, MNTTYPE_42) != 0)
  412.             continue;
  413.  
  414.         if (nnfscounters < MAXEXPORT) {
  415.             if (stat(mnt->mnt_dir, &st) < 0)
  416.                 continue;
  417.  
  418.             /*
  419.              * Not exported; skip it.
  420.              */
  421.             if (!is_exported(st.st_dev))
  422.                 continue;
  423.  
  424.             nc->nc_dev = st.st_dev;
  425.             nc->nc_name = savestr(mnt->mnt_dir);
  426.  
  427.             nnfscounters++;
  428.             nc++;
  429.         }
  430.     }
  431.  
  432.     (void) endmntent(fp);
  433. #endif /* SUNOS4 */
  434.  
  435. #ifdef SVR4
  436.     /*
  437.      * Open the list of mounted file systems.
  438.      */
  439.     if ((fp = fopen(MOUNTTABLE, "r")) == NULL) {
  440.         error(MOUNTTABLE);
  441.         finish(-1);
  442.     }
  443.  
  444.     nc = nfs_counters;
  445.  
  446.     /*
  447.      * Save the first MAXEXPORT file systems of type "ufs" or "sysv"
  448.      * which have been shared.  These are the ones which can
  449.      * be mounted through NFS.
  450.      */
  451.     while (getmntent(fp, mnt) == 0) {
  452.         if (strcmp(mnt->mnt_fstype, "ufs") != 0 &&
  453.             strcmp(mnt->mnt_fstype, "sysv") != 0)
  454.             continue;
  455.  
  456.         if (nnfscounters < MAXEXPORT) {
  457.             if (stat(mnt->mnt_mountp, &st) < 0)
  458.                 continue;
  459.  
  460.             /*
  461.              * Not exported; skip it.
  462.              */
  463.             if (!is_exported(mnt->mnt_mountp))
  464.                 continue;
  465.  
  466.             nc->nc_dev = st.st_dev;
  467.             nc->nc_name = savestr(mnt->mnt_mountp);
  468.  
  469.             nnfscounters++;
  470.             nc++;
  471.         }
  472.     }
  473.  
  474.     (void) fclose(fp);
  475. #endif /* SVR4 */
  476.  
  477. #ifdef ultrix
  478.     /*
  479.      * Get the mounted file information.
  480.      */
  481.     dummy = 0;
  482.     nmnts = getmnt(&dummy, fsData, sizeof(fsData), NOSTAT_MANY, 0);
  483.  
  484.     if (nmnts < 0) {
  485.         error("getmnt");
  486.         finish(-1);
  487.     }
  488.  
  489.     nc = nfs_counters;
  490.  
  491.     /*
  492.      * Save the first MAXEXPORT file systems which could have been
  493.      * exported.  These are what can be mounted through NFS.
  494.      */
  495.     if (nmnts > MAXEXPORT)
  496.         nmnts = MAXEXPORT;
  497.  
  498.     for (i=0; i < nmnts; i++) {
  499.         if (fsData[i].fd_flags & M_LOCAL) {
  500.             nc->nc_dev = fsData[i].fd_dev;
  501.             nc->nc_name = savestr(fsData[i].fd_path);
  502.  
  503.             nnfscounters++;
  504.             nc++;
  505.         }
  506.     }
  507. #endif /* ultrix */
  508.  
  509.     sort_nfs_counters();
  510. }
  511.  
  512. /*
  513.  * sort_nfs_counters - sort and assign places on the screen
  514.  */
  515. void
  516. sort_nfs_counters()
  517. {
  518.     register int i, j;
  519.  
  520.     (void) qsort(nfs_counters, nnfscounters, sizeof(NFSCounter), nfs_comp);
  521.  
  522.     /*
  523.      * Set screen coordinates for the ones which will be
  524.      * displayed.
  525.      */
  526.     for (i = 0, j = NFSLINES/2; i < NFSLINES/2; i++, j++) {
  527.         nfs_counters[i].nc_namex = SCR_NFS_NAME_X;
  528.         nfs_counters[j].nc_namex = SCR_NFS_NAME_X + SCR_MIDDLE;
  529.         nfs_counters[i].nc_namey = SCR_NFS_Y + i;
  530.         nfs_counters[j].nc_namey = SCR_NFS_Y + i;
  531.  
  532.         nfs_counters[i].nc_intx = SCR_NFS_INT_X;
  533.         nfs_counters[j].nc_intx = SCR_NFS_INT_X + SCR_MIDDLE;
  534.         nfs_counters[i].nc_inty = SCR_NFS_Y + i;
  535.         nfs_counters[j].nc_inty = SCR_NFS_Y + i;
  536.  
  537.         nfs_counters[i].nc_totx = SCR_NFS_TOT_X;
  538.         nfs_counters[j].nc_totx = SCR_NFS_TOT_X + SCR_MIDDLE;
  539.         nfs_counters[i].nc_toty = SCR_NFS_Y + i;
  540.         nfs_counters[j].nc_toty = SCR_NFS_Y + i;
  541.  
  542.         nfs_counters[i].nc_pctx = SCR_NFS_PCT_X;
  543.         nfs_counters[j].nc_pctx = SCR_NFS_PCT_X + SCR_MIDDLE;
  544.         nfs_counters[i].nc_pcty = SCR_NFS_Y + i;
  545.         nfs_counters[j].nc_pcty = SCR_NFS_Y + i;
  546.     }
  547. }
  548.  
  549. /*
  550.  * setup_fil_counters- setup file counter stuff.
  551.  */
  552. void
  553. setup_fil_counters()
  554. {
  555.     FILE *fp;
  556.     struct stat st;
  557.     register int i, j;
  558.     char fname[MAXPATHLEN];
  559.     register FileCounter *fc;
  560.  
  561.     (void) bzero((char *) fil_counters,
  562.         MAXEXPORT * sizeof(FileCounter));
  563.  
  564.     /*
  565.      * If we're not watching our own host, we can't look
  566.      * for individual files.
  567.      */
  568.     if (strcmp(myhost, dsthost) != 0)
  569.         return;
  570.  
  571.     /*
  572.      * Open the list of files to watch.
  573.      */
  574.     if ((fp = fopen(filelist, "r")) == NULL) {
  575.         error(filelist);
  576.         finish(-1);
  577.     }
  578.  
  579.     fc = fil_counters;
  580.  
  581.     /*
  582.      * Save the first MAXEXPORT file systems of type "4.2"
  583.      * which have been exported.  These are the ones which can
  584.      * be mounted through NFS.
  585.      */
  586.     while (fgets(fname, sizeof(fname), fp) != NULL) {
  587.         fname[strlen(fname)-1] = '\0';
  588.  
  589.         if (nfilecounters < MAXEXPORT) {
  590.             if (stat(fname, &st) < 0)
  591.                 continue;
  592.  
  593. #ifndef SVR4
  594.             /*
  595.              * Not on an exported file system; skip it.
  596.              */
  597.             if (!is_exported(st.st_dev)) {
  598.                 (void) fprintf(stderr, "warning: \"%s\" is not on an exported file system.\n", fname);
  599.                 continue;
  600.             }
  601. #endif
  602.  
  603.             fc->fc_dev = st.st_dev;
  604.             fc->fc_ino = st.st_ino;
  605.             fc->fc_name = savestr(fname);
  606.  
  607.             nfilecounters++;
  608.             fc++;
  609.         }
  610.     }
  611.  
  612.     (void) fclose(fp);
  613.  
  614.     (void) qsort(fil_counters, nfilecounters, sizeof(FileCounter), fil_comp);
  615.  
  616.     /*
  617.      * Set screen coordinates for the ones which will be
  618.      * displayed.
  619.      */
  620.     for (i = 0, j = NFSLINES/2; i < NFSLINES/2; i++, j++) {
  621.         fil_counters[i].fc_namex = SCR_NFS_NAME_X;
  622.         fil_counters[j].fc_namex = SCR_NFS_NAME_X + SCR_MIDDLE;
  623.         fil_counters[i].fc_namey = SCR_NFS_Y + i;
  624.         fil_counters[j].fc_namey = SCR_NFS_Y + i;
  625.  
  626.         fil_counters[i].fc_intx = SCR_NFS_INT_X;
  627.         fil_counters[j].fc_intx = SCR_NFS_INT_X + SCR_MIDDLE;
  628.         fil_counters[i].fc_inty = SCR_NFS_Y + i;
  629.         fil_counters[j].fc_inty = SCR_NFS_Y + i;
  630.  
  631.         fil_counters[i].fc_totx = SCR_NFS_TOT_X;
  632.         fil_counters[j].fc_totx = SCR_NFS_TOT_X + SCR_MIDDLE;
  633.         fil_counters[i].fc_toty = SCR_NFS_Y + i;
  634.         fil_counters[j].fc_toty = SCR_NFS_Y + i;
  635.  
  636.         fil_counters[i].fc_pctx = SCR_NFS_PCT_X;
  637.         fil_counters[j].fc_pctx = SCR_NFS_PCT_X + SCR_MIDDLE;
  638.         fil_counters[i].fc_pcty = SCR_NFS_Y + i;
  639.         fil_counters[j].fc_pcty = SCR_NFS_Y + i;
  640.     }
  641. }
  642.  
  643. /*
  644.  * Names of NFS procedures (MUST be kept in the right order)
  645.  *    two leading spaces make things look nicer
  646.  */
  647. char    *nfs_procs[] = {
  648.     "  NULLPROC",    "  GETATTR",    "  SETATTR",    "  GETROOT",
  649.     "  LOOKUP",    "  READLINK",    "  READ",    "  WCACHE",
  650.     "  WRITE",    "  CREATE",    "  REMOVE",    "  RENAME",
  651.     "  LINK",    "  SYMLINK",    "  MKDIR",    "  RMDIR",
  652.     "  READDIR",    "  STATFS",    0
  653. };
  654.  
  655. /*
  656.  * setup_proc_counters- setup procedure counter stuff.
  657.  */
  658. void
  659. setup_proc_counters()
  660. {
  661.     register int i;
  662.     register ProcCounter *pc;
  663.  
  664.     (void) bzero((char *) prc_counters,
  665.         MAXNFSPROC * sizeof(ProcCounter));
  666.  
  667.     for (i = 0; i < MAXNFSPROC; i++) {
  668.         prc_counters[i].pr_type = i;
  669.         prc_counters[i].pr_name = nfs_procs[i];
  670.     }
  671.  
  672.     sort_prc_counters();
  673. }
  674.  
  675. /*
  676.  * sort_prc_counters - sort and assign places on the screen
  677.  */
  678. sort_prc_counters()
  679. {
  680.     register int i;
  681.     register int numlines;
  682.  
  683.     (void) qsort(prc_counters, MAXNFSPROC, sizeof(ProcCounter), prc_comp);
  684.  
  685.     /* Create indirection index */
  686.     for (i = 0; i < MAXNFSPROC; i++)
  687.         prc_countmap[prc_counters[i].pr_type] = i;
  688.  
  689.     /*
  690.      * Set screen coordinates for the ones which will be
  691.      * displayed.
  692.      */
  693.     numlines = MAXNFSPROC;
  694.     if (MAXNFSPROC & 1)    /* round up to even number; extra space */
  695.         numlines++;        /* has been provided (see nfswatch.c)   */
  696.     if (NFSLINES < numlines)
  697.         numlines = NFSLINES;
  698.  
  699.     for (i = 0; i < numlines; i++) {
  700.         prc_counters[i].pr_namex = SCR_NFS_NAME_X;
  701.         prc_counters[i].pr_namey = SCR_NFS_Y + i;
  702.  
  703.         prc_counters[i].pr_intx = SCR_NFS_INT_X;
  704.         prc_counters[i].pr_inty = SCR_NFS_Y + i;
  705.  
  706.         prc_counters[i].pr_totx = SCR_NFS_TOT_X;
  707.         prc_counters[i].pr_toty = SCR_NFS_Y + i;
  708.  
  709.         prc_counters[i].pr_pctx = SCR_NFS_PCT_X;
  710.         prc_counters[i].pr_pcty = SCR_NFS_Y + i;
  711.  
  712.         prc_counters[i].pr_compx = SCR_NFS_COMP_X;
  713.         prc_counters[i].pr_compy = SCR_NFS_Y + i;
  714.  
  715.         prc_counters[i].pr_respx = SCR_NFS_RESP_X;
  716.         prc_counters[i].pr_respy = SCR_NFS_Y + i;
  717.  
  718.         prc_counters[i].pr_rsqrx = SCR_NFS_RSQR_X;
  719.         prc_counters[i].pr_rsqry = SCR_NFS_Y + i;
  720.  
  721.         prc_counters[i].pr_rmaxx = SCR_NFS_RMAX_X;
  722.         prc_counters[i].pr_rmaxy = SCR_NFS_Y + i;
  723.     }
  724. }
  725.  
  726. /*
  727.  * setup_clnt_counters- setup client counter stuff.
  728.  */
  729. void
  730. setup_clnt_counters()
  731. {
  732.     register int i;
  733.  
  734.     (void) bzero((char *) clnt_counters,
  735.         MAXCLIENTS * sizeof(ProcCounter));
  736.  
  737.     sort_clnt_counters();
  738. }
  739.  
  740. /*
  741.  * sort_clnt_counters - sort and assign places on the screen
  742.  */
  743. sort_clnt_counters()
  744. {
  745.     register int i, j;
  746.     register int numlines;
  747.  
  748.     (void) qsort(clnt_counters, nclientcounters, sizeof(ClientCounter),
  749.             clnt_comp);
  750.     ClientHashRebuild();
  751.  
  752.     /*
  753.      * Set screen coordinates for the ones which will be
  754.      * displayed.
  755.      */
  756.     numlines = nclientcounters;
  757.     if (numlines & 1)    /* round up to even number; nfswatch.h    */
  758.         numlines++;        /* must set MAXCLIENTS to even number    */
  759.     if (NFSLINES < numlines)
  760.         numlines = NFSLINES;
  761.  
  762.     for (i = 0, j = numlines/2; i < numlines/2; i++, j++) {
  763.         clnt_counters[i].cl_namex = SCR_NFS_NAME_X;
  764.         clnt_counters[j].cl_namex = SCR_NFS_NAME_X + SCR_MIDDLE;
  765.         clnt_counters[i].cl_namey = SCR_NFS_Y + i;
  766.         clnt_counters[j].cl_namey = SCR_NFS_Y + i;
  767.  
  768.         clnt_counters[i].cl_intx = SCR_NFS_INT_X;
  769.         clnt_counters[j].cl_intx = SCR_NFS_INT_X + SCR_MIDDLE;
  770.         clnt_counters[i].cl_inty = SCR_NFS_Y + i;
  771.         clnt_counters[j].cl_inty = SCR_NFS_Y + i;
  772.  
  773.         clnt_counters[i].cl_totx = SCR_NFS_TOT_X;
  774.         clnt_counters[j].cl_totx = SCR_NFS_TOT_X + SCR_MIDDLE;
  775.         clnt_counters[i].cl_toty = SCR_NFS_Y + i;
  776.         clnt_counters[j].cl_toty = SCR_NFS_Y + i;
  777.  
  778.         clnt_counters[i].cl_pctx = SCR_NFS_PCT_X;
  779.         clnt_counters[j].cl_pctx = SCR_NFS_PCT_X + SCR_MIDDLE;
  780.         clnt_counters[i].cl_pcty = SCR_NFS_Y + i;
  781.         clnt_counters[j].cl_pcty = SCR_NFS_Y + i;
  782.     }
  783. }
  784.  
  785. /*
  786.  * sort_auth_counters - sort and assign places on the screen.
  787.  */
  788. void
  789. sort_auth_counters()
  790. {
  791.     register int i, j;
  792.     register int numlines;
  793.  
  794.     (void) qsort(auth_counters, nauthcounters, sizeof(AuthCounter),
  795.              auth_comp);
  796.  
  797.     /*
  798.      * Set screen coordinates for the ones which will be displayed.
  799.      */
  800.     numlines = nauthcounters;
  801.  
  802.     if (numlines & 1)
  803.         numlines++;
  804.  
  805.     if (NFSLINES < numlines)
  806.         numlines = NFSLINES;
  807.  
  808.     for (i = 0, j = numlines / 2; i < numlines / 2; i++, j++) {
  809.         auth_counters[i].ac_namex = SCR_NFS_NAME_X;
  810.         auth_counters[j].ac_namex = SCR_NFS_NAME_X + SCR_MIDDLE;
  811.         auth_counters[i].ac_namey = SCR_NFS_Y + i;
  812.         auth_counters[j].ac_namey = SCR_NFS_Y + i;
  813.  
  814.         auth_counters[i].ac_intx = SCR_NFS_INT_X;
  815.         auth_counters[j].ac_intx = SCR_NFS_INT_X + SCR_MIDDLE;
  816.         auth_counters[i].ac_inty = SCR_NFS_Y + i;
  817.         auth_counters[j].ac_inty = SCR_NFS_Y + i;
  818.  
  819.         auth_counters[i].ac_totx = SCR_NFS_TOT_X;
  820.         auth_counters[j].ac_totx = SCR_NFS_TOT_X + SCR_MIDDLE;
  821.         auth_counters[i].ac_toty = SCR_NFS_Y + i;
  822.         auth_counters[j].ac_toty = SCR_NFS_Y + i;
  823.  
  824.         auth_counters[i].ac_pctx = SCR_NFS_PCT_X;
  825.         auth_counters[j].ac_pctx = SCR_NFS_PCT_X + SCR_MIDDLE;
  826.         auth_counters[i].ac_pcty = SCR_NFS_Y + i;
  827.         auth_counters[j].ac_pcty = SCR_NFS_Y + i;
  828.     }
  829. }
  830.  
  831. /*
  832.  * auth_comp - compare authentication counters for qsort.
  833.  */
  834. int
  835. auth_comp(a, b)
  836. register AuthCounter *a, *b;
  837. {
  838.     if (sortbyusage) {
  839.         if ((long) b->ac_interval == (long) a->ac_interval)
  840.             return((long) b->ac_total - (long) a->ac_total);
  841.         else
  842.             return((long) b->ac_interval - (long) a->ac_interval);
  843.     }
  844.     else {
  845.         return(strcmp(a->ac_name, b->ac_name));
  846.     }
  847. }
  848.  
  849. /*
  850.  * is_exported - return whether or not a file system is exported.
  851.  */
  852. #ifdef SUNOS4
  853. int
  854. is_exported(dev)
  855. register dev_t dev;
  856. {
  857.     FILE *fp;
  858.     struct stat st;
  859.     register dev_t *exp;
  860.     static int nexported = -1;
  861.     register struct exportent *xent;
  862.     static dev_t exported[MAXEXPORT];
  863.  
  864.     /*
  865.      * First time through, read the export table and
  866.      * save all the device numbers.
  867.      */
  868.     if (nexported < 0) {
  869.         /*
  870.          * If there's no export file, it must
  871.          * not be exported.
  872.          */
  873.         if ((fp = setexportent(TABFILE)) == NULL)
  874.             return(FALSE);
  875.  
  876.         nexported = 0;
  877.  
  878.         while ((xent = getexportent(fp)) != NULL) {
  879.             if (stat(xent->xent_dirname, &st) < 0)
  880.                 continue;
  881.  
  882.             if (nexported < MAXEXPORT)
  883.                 exported[nexported++] = st.st_dev;
  884.         }
  885.  
  886.         (void) endexportent(fp);
  887.     }
  888.  
  889.     /*
  890.      * Search the exported device numbers for this device number.
  891.      */
  892.     for (exp = exported; exp < &exported[nexported]; exp++) {
  893.         if (dev == *exp)
  894.             return(TRUE);
  895.     }
  896.  
  897.     return(FALSE);
  898. }
  899. #endif /* SUNOS4 */
  900.  
  901. #ifdef SVR4
  902. int
  903. is_exported(fsname)
  904. char *fsname;
  905. {
  906.     FILE *fp;
  907.     register int i;
  908.     static int nshared = -1;
  909.     static char *shared[MAXEXPORT];
  910.     char line[BUFSIZ], path[BUFSIZ];
  911.  
  912.     if (nshared < 0) {
  913.         nshared = 0;
  914.  
  915.         if ((fp = fopen(SHARETAB, "r")) == NULL)
  916.             return(0);
  917.  
  918.         while (fgets(line, sizeof(line), fp) != NULL) {
  919.             if (*line == '#' || *line == '\n')
  920.                 continue;
  921.  
  922.             sscanf(line, "%s", path);
  923.  
  924.             if (nshared < MAXEXPORT)
  925.                 shared[nshared++] = savestr(path);
  926.         }
  927.  
  928.         fclose(fp);
  929.     }
  930.  
  931.     for (i=0; i < nshared; i++) {
  932.         if (strcmp(fsname, shared[i]) == 0)
  933.             return(1);
  934.     }
  935.  
  936.     return(0);
  937. }
  938. #endif /* SVR4 */
  939.  
  940. #if defined(sgi) || defined(ultrix)
  941. int
  942. is_exported(dev)
  943. register dev_t dev;
  944. {
  945.     return(TRUE);
  946. }
  947. #endif
  948.  
  949. /*
  950.  * nfs_comp - compare NFS counters for qsort.
  951.  */
  952. int
  953. nfs_comp(a, b)
  954. register NFSCounter *a, *b;
  955. {
  956.     if (sortbyusage) {
  957.         if (((long)b->nc_interval) == ((long)a->nc_interval))
  958.         return(((long)b->nc_total) - ((long)a->nc_total));
  959.         else
  960.         return(((long)b->nc_interval) - ((long)a->nc_interval));
  961.     }
  962.     else
  963.         return(strcmp(a->nc_name, b->nc_name));
  964. }
  965.  
  966. /*
  967.  * fil_comp = compare file counters for qsort.
  968.  */
  969. int
  970. fil_comp(a, b)
  971. register FileCounter *a, *b;
  972. {
  973.     if (sortbyusage) {
  974.         if (((long)b->fc_interval) == ((long)a->fc_interval))
  975.         return(((long)b->fc_total) - ((long)a->fc_total));
  976.         else
  977.         return(((long)b->fc_interval) - ((long)a->fc_interval));
  978.     }
  979.     else
  980.         return(strcmp(a->fc_name, b->fc_name));
  981. }
  982.  
  983. /*
  984.  * prc_comp - compare procedure counters for qsort.
  985.  */
  986. int
  987. prc_comp(a, b)
  988. register ProcCounter *a, *b;
  989. {
  990.     if (sortbyusage) {
  991.         if (((long)b->pr_interval) == ((long)a->pr_interval))
  992.         return(((long)b->pr_total) - ((long)a->pr_total));
  993.         else
  994.         return(((long)b->pr_interval) - ((long)a->pr_interval));
  995.     }
  996.     else
  997.         return(strcmp(a->pr_name, b->pr_name));
  998. }
  999.  
  1000. /*
  1001.  * clnt_comp - compare client counters for qsort.
  1002.  */
  1003. int
  1004. clnt_comp(a, b)
  1005. register ClientCounter *a, *b;
  1006. {
  1007.     if (sortbyusage) {
  1008.         if (((long)b->cl_interval) == ((long)a->cl_interval))
  1009.         return(((long)b->cl_total) - ((long)a->cl_total));
  1010.         else
  1011.         return(((long)b->cl_interval) - ((long)a->cl_interval));
  1012.     }
  1013.     else
  1014.         return(strcmp(a->cl_name, b->cl_name));
  1015. }
  1016.  
  1017. /*
  1018.  * usage - print a usage message and exit.
  1019.  */
  1020. void
  1021. usage()
  1022. {
  1023.         fprintf(stderr, "Usage: %s [-dst host] [-src host]", pname);
  1024.     fprintf(stderr, " [-server host] [-all] [-dev device]\n");
  1025.     fprintf(stderr, "       [-allif] [-f filelist] [-lf logfile] ");
  1026.     fprintf(stderr, " [-sf snapfile] [-map mapfile]\n");
  1027.     fprintf(stderr, "       [-T maxtime] [-t timeout]");
  1028.     fprintf(stderr, " [-fs] [-if] [-auth] [-procs] [-clients]\n");
  1029.     fprintf(stderr, "       [-usage] [-l] [-bg]\n");
  1030.                             
  1031.     finish(-1);
  1032. }
  1033.  
  1034. /*
  1035.  * wakeup - wake up for a screen update.
  1036.  */
  1037. void
  1038. wakeup()
  1039. {
  1040.     struct timeval tv;
  1041.  
  1042.     /*
  1043.      * See if we've exceeded the total time to run.
  1044.      */
  1045.     gettimeofday(&tv, 0);
  1046.  
  1047.     if ((totaltime > 0) && ((tv.tv_sec - starttime.tv_sec) > totaltime))
  1048.         finish(0);
  1049.  
  1050.     /*
  1051.      * Re-sort and re-do the labels.
  1052.      */
  1053.     if (sortbyusage) {
  1054.         sort_nfs_counters();
  1055.         sort_prc_counters();
  1056.         sort_clnt_counters();
  1057.         sort_auth_counters();
  1058.     }
  1059.  
  1060.     if (!bgflag) {
  1061.         label_screen();
  1062.         update_screen();
  1063.     }
  1064.  
  1065.     if (logging)
  1066.         update_logfile();
  1067.  
  1068.     clear_vars();
  1069. }
  1070.  
  1071. /*
  1072.  * dlt_name - return string giving name for a data link type code
  1073.  */
  1074. char *
  1075. dlt_name(dlt)
  1076. int dlt;
  1077. {
  1078.     switch(dlt) {
  1079.     case DLT_NULL:
  1080.         return("no link-layer encapsulation");
  1081.     case DLT_EN10MB:
  1082.         return("Ethernet");
  1083.     case DLT_EN3MB:
  1084.         return("Experimental Ethernet");
  1085.     case DLT_AX25:
  1086.         return("Amateur Radio AX.25");
  1087.     case DLT_PRONET:
  1088.         return("ProNET");
  1089.     case DLT_CHAOS:
  1090.         return("Chaosnet");
  1091.     case DLT_IEEE802:
  1092.         return("IEEE802");
  1093.     case DLT_ARCNET:
  1094.         return("ARCNET");
  1095.     case DLT_SLIP:
  1096.         return("SLIP");
  1097.     case DLT_PPP:
  1098.         return("PPP");
  1099.     case DLT_FDDI:
  1100.         return("FDDI");
  1101.     default:
  1102.         return("[unknown LAN type]");
  1103.     }
  1104. }
  1105.  
  1106. static int    nummap = 0;
  1107. static char    *fs_maps[1024];
  1108.  
  1109. void
  1110. setup_map_file()
  1111. {
  1112.     int len;
  1113.     char *p;
  1114.     FILE *fp;
  1115.     char *malloc();
  1116.     char fs[BUFSIZ], alias[BUFSIZ];
  1117.     char line[BUFSIZ], trans[BUFSIZ];
  1118.  
  1119.     if ((fp = fopen(mapfile, "r")) == NULL) {
  1120.         error(mapfile);
  1121.         finish(-1);
  1122.     }
  1123.  
  1124.     while (fgets(line, sizeof(line), fp) != NULL) {
  1125.         if (sscanf(line, "%s %s", fs, alias) != 2)
  1126.             continue;
  1127.  
  1128.         strcpy(trans, fs);
  1129.         len = strlen(fs) + 1;
  1130.  
  1131.         strcpy(trans + len, alias);
  1132.         len += strlen(alias) + 1;
  1133.  
  1134.         if ((fs_maps[nummap] = malloc(len)) == NULL) {
  1135.             (void) fprintf(stderr, "%s: out of memory.\n", pname);
  1136.             finish(-1);
  1137.         }
  1138.  
  1139.         bcopy(trans, fs_maps[nummap], len);
  1140.         nummap++;
  1141.     }
  1142.  
  1143.     fclose(fp);
  1144. }
  1145.  
  1146. char *
  1147. map_fs_name(fs)
  1148. char *fs;
  1149. {
  1150.     int i;
  1151.  
  1152.     for (i=0; i < nummap; i++) {
  1153.         if (strcmp(fs, fs_maps[i]) == 0)
  1154.             return(fs_maps[i] + strlen(fs_maps[i]) + 1);
  1155.     }
  1156.  
  1157.     return(fs);
  1158. }
  1159.